home *** CD-ROM | disk | FTP | other *** search
/ Programming Languages Suite / ProgramD2.iso / Borland / Borland Pascal with Objects 7.0 / RWDEMOS.ZIP / BITBTN.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1992-10-27  |  21.7 KB  |  721 lines

  1. {************************************************}
  2. {                                                }
  3. {   Resource Workshop Demo library               }
  4. {   Copyright (c) 1992 by Borland International  }
  5. {                                                }
  6. {************************************************}
  7.  
  8. library BitBtn;
  9.  
  10. uses WinTypes, WinProcs, Strings, CustCntl, BitBtnCo;
  11.  
  12. {$R BITBTN.RES}
  13.  
  14. { ==============================================================
  15.   Bitmaped button custom control.
  16.   ============================================================== }
  17.  
  18. const
  19.   ofReserved    = 0;  { Used by the dialog manager }
  20.   ofState       = 2;
  21.   ofDownBits    = 4;
  22.   ofUpBits      = 6;
  23.   ofFocUpBits   = 8;
  24.   ofSize        = 10; { Amount of window extra bytes to use }
  25.  
  26. const
  27.   bdBorderWidth = 1;
  28.  
  29. const
  30.   bsDisabled    = $0001;
  31.   bsFocus       = $0002;
  32.   bsKeyDown     = $0004;
  33.   bsMouseDown   = $0008;
  34.   bsMouseUpDown = $0010;
  35.   bsDefault     = $0020;
  36.  
  37. { GetAppInstance -----------------------------------------------
  38.     Returns a handle to the current client application.
  39.   -------------------------------------------------------------- }
  40. function GetAppInstance: THandle; near; assembler;
  41. asm
  42.     PUSH    SS
  43.     CALL    GlobalHandle
  44. end;
  45.  
  46. { IsWorkshopWindow ---------------------------------------------
  47.     Returns true if the window belongs to Resource Workshop.
  48.     Used to determine if the control is being edited; allowing
  49.     the LoadResRW function to be called.
  50.   -------------------------------------------------------------- }
  51. function IsWorkshopWindow(Wnd: HWnd): Boolean;
  52. var
  53.   Parent: HWnd;
  54.   ClassName: array[0..80] of Char;
  55. begin
  56.   Parent := Wnd;
  57.   repeat
  58.     Wnd := Parent;
  59.     Parent := GetParent(Wnd);
  60.   until Parent = 0;
  61.   GetClassName(Wnd, ClassName, SizeOf(ClassName));
  62.   IsWorkshopWindow := StrComp(ClassName, 'rwswnd') = 0;
  63. end;
  64.  
  65. { LoadResRW ----------------------------------------------------
  66.     Load a resource from Resource Workshop. Initialized by
  67.     ListClasses below.
  68.   -------------------------------------------------------------- }
  69. var
  70.   LoadResRW: TLoad;
  71.  
  72. { LoadBitmapRW -------------------------------------------------
  73.     Load a bitmap from Resource Workshop.  *MUST* be called from
  74.     inside resource workshop (IsWorkshopWindow must be true).
  75.   -------------------------------------------------------------- }
  76. function LoadBitmapRW(szTitle: PChar): HBitmap;
  77. var
  78.   Res: THandle;
  79.   Bits: PBitMapInfoHeader;
  80.   DC: HDC;
  81.   nColors: Integer;
  82.  
  83. function GetDInColors(BitCount: Integer): Integer;
  84. begin
  85.   case BitCount of
  86.     1, 3, 4, 8: GetDInColors := 1 shl BitCount;
  87.   else
  88.     GetDInColors := 0;
  89.   end;
  90. end;
  91.  
  92. begin
  93.   LoadBitmapRW := 0;
  94.   Res := LoadResRW(rt_Bitmap, szTitle);
  95.   if Res <> 0 then
  96.   begin
  97.     Bits := GlobalLock(Res);
  98.     if Bits^.biSize = SizeOf(TBitMapInfoHeader) then
  99.     begin
  100.       nColors := GetDInColors(Bits^.biBitCount);
  101.       DC := GetDC(0);
  102.       if DC <> 0 then
  103.       begin
  104.     LoadBitmapRW := CreateDIBitmap(DC, Bits^, cbm_Init,
  105.       Pointer(LongInt(Bits) + SizeOf(Bits^) +
  106.       nColors * SizeOf(TRGBQuad)), PBitmapInfo(Bits)^,
  107.       dib_RGB_Colors);
  108.     ReleaseDC(0, DC);
  109.       end;
  110.     end;
  111.     GlobalUnlock(Res);
  112.     GlobalFree(Res);
  113.   end;
  114. end;
  115.  
  116. { BitButtonWinFn -----------------------------------------------
  117.     Button window procedure.
  118.   -------------------------------------------------------------- }
  119. function BitButtonWinFn(HWindow: HWnd; Message: Word; wParam: Word;
  120.   lParam: Longint): Longint; export;
  121. var
  122.   DC: HDC;
  123.   BitsNumber: Integer;
  124.   Bitmap: TBitmap;
  125.   Rect: TRect;
  126.   Pt: TPoint;
  127.   PS: TPaintStruct;
  128.  
  129. { Get ----------------------------------------------------------
  130.     Get a window instance word.
  131.   -------------------------------------------------------------- }
  132. function Get(Ofs: Integer): Word;
  133. begin
  134.   Get := GetWindowWord(HWindow, Ofs);
  135. end;
  136.  
  137. { SetWord ------------------------------------------------------
  138.     Set the value of a window instance word.
  139.   -------------------------------------------------------------- }
  140. procedure SetWord(Ofs: Integer; Val: Word);
  141. begin
  142.   SetWindowWord(HWindow, Ofs, Val);
  143. end;
  144.  
  145. { State --------------------------------------------------------
  146.     Get the button's state word.
  147.   -------------------------------------------------------------- }
  148. function State: Word;
  149. begin
  150.   State := Get(ofState);
  151. end;
  152.  
  153. { DownBits -----------------------------------------------------
  154.     Get the "down" bitmap of the button.
  155.   -------------------------------------------------------------- }
  156. function DownBits: Word;
  157. begin
  158.   DownBits := Get(ofDownBits);
  159. end;
  160.  
  161. { UpBits -------------------------------------------------------
  162.     Get the "up" bitmap of the button.
  163.   -------------------------------------------------------------- }
  164. function UpBits: Word;
  165. begin
  166.   UpBits := Get(ofUpBits);
  167. end;
  168.  
  169. { FocUpBits ----------------------------------------------------
  170.     Get the "focused up" bitmap of the button.
  171.   -------------------------------------------------------------- }
  172. function FocUpBits: Word;
  173. begin
  174.   FocUpBits := Get(ofFocUpBits);
  175. end;
  176.  
  177. { GetState -----------------------------------------------------
  178.     Get the value of a state bit.
  179.   -------------------------------------------------------------- }
  180. function GetState(AState: Word): Boolean;
  181. begin
  182.   GetState := (State and AState) = AState;
  183. end;
  184.  
  185. { Paint --------------------------------------------------------
  186.     Paint the button.  Called in responce to a WM_PAINT message
  187.     and whenever the button changes state (called by Repaint).
  188.   -------------------------------------------------------------- }
  189. procedure Paint(DC: HDC);
  190. const
  191.   coGray = $00C0C0C0;
  192. var
  193.   MemDC: HDC;
  194.   Bits, Oldbitmap: HBitmap;
  195.   BorderBrush, OldBrush: HBrush;
  196.   LogBrush: TLogBrush;
  197.   Frame: TRect;
  198.   Height, Width: Integer;
  199. begin
  200.   if (State and (bsMouseDown + bsKeyDown) <> 0) and
  201.       not GetState(bsMouseUpDown) then
  202.     Bits := DownBits
  203.   else
  204.     if GetState(bsFocus) then
  205.       Bits := FocUpBits
  206.     else
  207.       Bits := UpBits;
  208.  
  209.   { Draw border }
  210.   GetClientRect(HWindow, Frame);
  211.   Height := Frame.bottom - Frame.top;
  212.   Width := Frame.right - Frame.left;
  213.  
  214.   if GetState(bsDefault) then
  215.     BorderBrush := GetStockObject(Black_Brush)
  216.   else BorderBrush := GetStockObject(White_Brush);
  217.   OldBrush := SelectObject(DC, BorderBrush);
  218.   PatBlt(DC, Frame.left, Frame.top, Width, bdBorderWidth, PatCopy);
  219.   PatBlt(DC, Frame.left, Frame.top, bdBorderWidth, Height, PatCopy);
  220.   PatBlt(DC, Frame.left, Frame.bottom - bdBorderWidth, Width,
  221.     bdBorderWidth, PatCopy);
  222.   PatBlt(DC, Frame.right - bdBorderWidth, Frame.top, bdBorderWidth,
  223.     Height, PatCopy);
  224.   SelectObject(DC, OldBrush);
  225.  
  226.   { Draw bitmap }
  227.   MemDC := CreateCompatibleDC(DC);
  228.   OldBitmap := SelectObject(MemDC, Bits);
  229.   GetObject(Bits, Sizeof(Bitmap), @Bitmap);
  230.   if GetState(bsDisabled) then
  231.   begin
  232.     { Gray out the button }
  233.     OldBrush := SelectObject(DC, CreateSolidBrush(coGray));
  234.     PatBlt(DC, bdBorderWidth, bdBorderWidth, Bitmap.bmWidth,
  235.       Bitmap.bmHeight, PatCopy);
  236.     DeleteObject(SelectObject(DC, OldBrush));
  237.  
  238.     { Draw the bitmap through a checked brush }
  239.     LogBrush.lbStyle := bs_Pattern;
  240.     LogBrush.lbHatch := LoadBitmap(HInstance, MakeIntResource(btDisableBits));
  241.     OldBrush := SelectObject(DC, CreateBrushIndirect(LogBrush));
  242.     BitBlt(DC, bdBorderWidth, bdBorderWidth, Bitmap.bmWidth,
  243.       Bitmap.bmHeight, MemDC, 0, 0, $00A803A9 {DPSoa});
  244.     DeleteObject(SelectObject(DC, OldBrush));
  245.     DeleteObject(LogBrush.lbHatch);
  246.   end
  247.   else
  248.     BitBlt(DC, bdBorderWidth, bdBorderWidth, Bitmap.bmWidth,
  249.       Bitmap.bmHeight, MemDC, 0, 0, srcCopy);
  250.   SelectObject(MemDC, OldBitmap);
  251.  
  252.   DeleteDC(MemDC);
  253. end;
  254.  
  255. { Repaint ------------------------------------------------------
  256.     Repaint the button. Called whenever the button changes
  257.     state.
  258.   -------------------------------------------------------------- }
  259. procedure Repaint;
  260. var
  261.   DC: HDC;
  262. begin
  263.   DC := GetDC(HWindow);
  264.   Paint(DC);
  265.   ReleaseDC(HWindow, DC);
  266. end;
  267.  
  268. { SetState -----------------------------------------------------
  269.     Sets the value of a state bit.  If the word changes value
  270.     the button is repainted.
  271.   -------------------------------------------------------------- }
  272. procedure SetState(AState: Word; Enable: Boolean);
  273. var
  274.   OldState, NewState: Word;
  275. begin
  276.   OldState := State;
  277.   if Enable then NewState := OldState or AState
  278.   else NewState := OldState and not AState;
  279.   if NewState <> OldState then
  280.   begin
  281.     SetWord(ofState, NewState);
  282.     Repaint;
  283.   end;
  284. end;
  285.  
  286. { InMe ---------------------------------------------------------
  287.     Returns true if the given point is in within the border of
  288.     the button.
  289.   -------------------------------------------------------------- }
  290. function InMe(lPoint: Longint): Boolean;
  291. var
  292.   R: TRect;
  293.   Point: TPoint absolute lPoint;
  294. begin
  295.   GetClientRect(HWindow, R);
  296.   InflateRect(R, -bdBorderWidth, -bdBorderWidth);
  297.   InMe := PtInRect(R, Point);
  298. end;
  299.  
  300. { ButtonPressed ------------------------------------------------
  301.     Called when the button is pressed by either the keyboard or
  302.     by the mouse.
  303.   -------------------------------------------------------------- }
  304. procedure ButtonPressed;
  305. begin
  306.   SetState(bsMouseDown + bsMouseUpDown + bsKeyDown, False);
  307.   SendMessage(GetParent(HWindow), wm_Command, GetDlgCtrlID(HWindow),
  308.     Longint(HWindow));
  309. end;
  310.  
  311. { LoadBits -----------------------------------------------------
  312.     Load the bitmap for the button or the "NO BITMAP" version
  313.     if it does not exist.
  314.   -------------------------------------------------------------- }
  315. procedure LoadBits(Wrd: Word; MapNumber: Word);
  316. var
  317.   MapBits: HBitmap;
  318. begin
  319.   MapBits := LoadBitmap(HInstance, pChar(MapNumber));
  320.   if MapBits = 0 then
  321.     if IsWorkshopWindow(HWindow) then
  322.       MapBits := LoadBitmapRW(pChar(MapNumber))
  323.     else
  324.       MapBits := LoadBitmap(GetAppInstance, pChar(MapNumber));
  325.   if MapBits = 0 then
  326.     MapBits := LoadBitmap(HInstance, pChar(MapNumber - Get(gww_ID)));
  327.   SetWord(Wrd, MapBits);
  328. end;
  329.  
  330. begin
  331.   BitButtonWinFn := 0;
  332.   case Message of
  333.     wm_Create:
  334.       begin
  335.     { Detect EGA monitor }
  336.     DC := GetDC(0);
  337.     if (GetSystemMetrics(sm_CYScreen) < 480) or
  338.         (GetDeviceCaps(DC, numColors) < 16) then
  339.       BitsNumber := 2000 + Get(gww_ID)
  340.     else
  341.       BitsNumber := 1000 + Get(gww_ID);
  342.     ReleaseDC(0, DC);
  343.  
  344.     { Load bitmaps from resource }
  345.     LoadBits(ofUpBits, BitsNumber);
  346.     LoadBits(ofDownBits, BitsNumber + 2000);
  347.     LoadBits(ofFocUpBits, BitsNumber + 4000);
  348.  
  349.     { Adjust size of button to size of bitmap }
  350.     GetObject(DownBits, SizeOf(Bitmap), @Bitmap);
  351.     GetWindowRect(HWindow, Rect);
  352.     Pt.X := Rect.Left;
  353.     Pt.Y := Rect.Top;
  354.     ScreenToClient(PCreateStruct (lParam)^.hwndParent, Pt);
  355.       MoveWindow(HWindow, Pt.X, Pt.Y,
  356.       Bitmap.bmWidth + bdBorderWidth * 2,
  357.       Bitmap.bmHeight + bdBorderWidth * 2, False);
  358.  
  359.     { Intialize button state }
  360.     with PCreateStruct(lParam)^ do
  361.     begin
  362.       if style and $1F = bs_DefPushButton then
  363.         SetState(bsDefault, True);
  364.       if style and ws_Disabled <> 0 then
  365.         SetState(bsDisabled, True);
  366.     end;
  367.       end;
  368.     wm_NCDestroy:
  369.       begin
  370.     { Destroy all saved bitmaps before the button is destroyed }
  371.     BitButtonWinFn := DefWindowProc(HWindow, Message, wParam, lParam);
  372.     DeleteObject(UpBits);
  373.     DeleteObject(DownBits);
  374.     DeleteObject(FocUpBits);
  375.       end;
  376.     wm_Paint:
  377.       begin
  378.     BeginPaint(HWindow, PS);
  379.     Paint(PS.hDC);
  380.     EndPaint(HWindow, PS);
  381.       end;
  382.     wm_EraseBkGnd:
  383.       begin
  384.     { Squelch the painting of the background to eliminate flicker }
  385.       end;
  386.     wm_Enable:
  387.       SetState(bsDisabled, wParam <> 0);
  388.     wm_SetFocus:
  389.       SetState(bsFocus, True);
  390.     wm_KillFocus:
  391.       SetState(bsFocus or bsKeyDown or bsMouseDown or bsMouseUpDown, False);
  392.     wm_KeyDown:
  393.       if (wParam = $20) and not GetState(bsKeyDown) and
  394.       not GetState(bsMouseDown) then
  395.     SetState(bsKeyDown, True);
  396.     wm_KeyUp:
  397.       if (wParam = $20) and GetState(bsKeyDown) then
  398.         ButtonPressed;
  399.     wm_LButtonDblClk, wm_LButtonDown:
  400.       if InMe(lParam) and not GetState(bsKeyDown) then
  401.       begin
  402.     if GetFocus <> HWindow then SetFocus(HWindow);
  403.     SetState(bsMouseDown, True);
  404.     SetCapture(HWindow);
  405.       end;
  406.     wm_MouseMove:
  407.       if GetState(bsMouseDown) then
  408.     SetState(bsMouseUpDown, not InMe(lParam));
  409.     wm_LButtonUp:
  410.       if GetState(bsMouseDown) then
  411.       begin
  412.     ReleaseCapture;
  413.     if not GetState(bsMouseUpDown) then ButtonPressed
  414.     else SetState(bsMouseDown + bsMouseUpDown, False);
  415.       end;
  416.  
  417.     { *** Handling the rest of these messages are what, at least for
  418.           the dialog manager, makes a push button a push button.  ***}
  419.     wm_GetDlgCode:
  420.       { Sent by the dialog manager to determine the control kind of
  421.     a child window.  Returning dlgc_DefPushButton or
  422.     dlgc_UndefPushButton causes the dialog manager to treat the
  423.     control like a button, sending the bm_SetStyle message to
  424.     move the default button style to the currenly focused button.
  425.  
  426.         The dlgc_Button constant is not documented by Microsoft
  427.         (however, it is documented for OS/2 PM, and appears to work
  428.         the same). If this constant is or'd in, the windows dialog
  429.         manager will take care of all accelerator key processing,
  430.         sending bm_SetState and bm_SetStyle messages when an
  431.         acclerator key is pressed. There is a side effect to using
  432.         the message, however, the dialog manager messes with the word
  433.         at offset 0 from the user Window words. }
  434.  
  435.       if GetState(bsDefault) then
  436.     BitButtonWinFn:= dlgc_DefPushButton or dlgc_Button
  437.       else
  438.     BitButtonWinFn := dlgc_UndefPushButton or dlgc_Button;
  439.     bm_GetState:
  440.       BitButtonWinFn := Integer(GetState(bsKeyDown));
  441.     bm_SetState:
  442.       SetState(bsKeyDown, wParam <> 0);
  443.     bm_SetStyle:
  444.       { Sent by the dialog manager when the button receives or looses
  445.     focus and is not the default button, or when another button
  446.     receives the focus and this button is the default button. }
  447.       SetState(bsDefault, wParam = bs_DefPushButton);
  448.   else
  449.     BitButtonWinFn := DefWindowProc(HWindow, Message, wParam, lParam);
  450.   end;
  451. end;
  452.  
  453. { ==============================================================
  454.   Custom contol interface routines.
  455.   ============================================================== }
  456.  
  457. { BitBtnInfo ---------------------------------------------------
  458.    Return the information about the capabilities of the
  459.    bit button class.
  460.   -------------------------------------------------------------- }
  461. function BitBtnInfo: THandle; export;
  462. var
  463.   hInfo: THandle;
  464.   Info: PRWCtlInfo;
  465. begin
  466.   hInfo := GlobalAlloc(gmem_Share or gmem_ZeroInit,
  467.     SizeOf(TRWCtlInfo));
  468.   if hInfo <> 0 then
  469.   begin
  470.     Info := GlobalLock(hInfo);
  471.     with Info^ do
  472.     begin
  473.       wVersion := $100;         { Version 1.00 }
  474.       wCtlTypes := 2;           { 2 types }
  475.       StrCopy(szClass, 'BitButton');
  476.       StrCopy(szTitle, 'Button');
  477.  
  478.       { Normal (Un-default) push button type }
  479.       with ctType[0] do
  480.       begin
  481.     wWidth := 63 or $8000;
  482.     wHeight := 39 or $8000;
  483.     StrCopy(szDescr, 'Push Button');
  484.     dwStyle := bs_PushButton or ws_TabStop;
  485.     hToolBit := LoadBitmap(HInstance, MakeIntResource(btUndefBits));
  486.     hDropCurs := LoadCursor(HInstance, MakeIntResource(crUndefCurs));
  487.       end;
  488.  
  489.       { Default push button type }
  490.       with ctType[1] do
  491.       begin
  492.     wWidth := 63 or $8000;
  493.     wHeight := 39 or $8000;
  494.     StrCopy(szDescr, 'Default Push Button');
  495.     dwStyle := bs_DefPushButton or ws_TabStop;
  496.     hToolBit := LoadBitmap(HInstance, MakeIntResource(btDefBits));
  497.     hDropCurs := LoadCursor(HInstance, MakeIntResource(crDefCurs));
  498.       end;
  499.     end;
  500.     GlobalUnlock(hInfo);
  501.   end;
  502.   BitBtnInfo := hInfo;
  503. end;
  504.  
  505. type
  506.   PParamRec = ^TParamRec;
  507.   TParamRec = record
  508.     CtlStyle: THandle;
  509.     IdToStr: TIdToStr;
  510.     StrToId: TStrToId;
  511.   end;
  512.  
  513. { BitBtnStyleDlg -----------------------------------------------
  514.     Style dialog's dialog hook.  Used by the dialog and called
  515.     when the control is double-clicked inside the dialog
  516.     editor.
  517.   -------------------------------------------------------------- }
  518. function BitBtnStyleDlg(HWindow: HWnd; Message: Word; wParam: Word;
  519.   lParam: Longint): Longint; export;
  520. const
  521.   Prop = 'Prop';
  522. var
  523.   hRec: THandle;
  524.   Rec: PParamRec;
  525.   Style: PCtlStyle;
  526.   S: array[0..256] of Char;
  527.   Radio: Integer;
  528. begin
  529.   case Message of
  530.     wm_InitDialog:
  531.       begin
  532.     hRec := LoWord(lParam);
  533.     Rec := GlobalLock(hRec);
  534.     Style := GlobalLock(Rec^.CtlStyle);
  535.     SetProp(HWindow, Prop, hRec);
  536.     with Rec^, Style^ do
  537.     begin
  538.       { Set caption }
  539.       SetDlgItemText(HWindow, idCaption, szTitle);
  540.  
  541.       { Set control id }
  542.       IdToStr(wId, S, SizeOf(S));
  543.       SetDlgItemText(HWindow, idControlId, S);
  544.  
  545.       { Set type radio buttons }
  546.       if dwStyle and $F = bs_DefPushButton then
  547.         Radio := idDefaultButton
  548.       else
  549.             Radio := idPushButton;
  550.       CheckRadioButton(HWindow, idDefaultButton, idPushButton,
  551.         Radio);
  552.  
  553.       { Initialize Tab Stop check box }
  554.       CheckDlgButton(HWindow, idTabStop,
  555.         Integer(dwStyle and ws_TabStop <> 0));
  556.  
  557.       { Initialize Disabled check box }
  558.       CheckDlgButton(HWindow, idDisabled,
  559.         Integer(dwStyle and ws_Disabled <> 0));
  560.  
  561.       { Initialize Group check box }
  562.       CheckDlgButton(HWindow, idGroup,
  563.         Integer(dwStyle and ws_Group <> 0));
  564.     end;
  565.     GlobalUnlock(Rec^.CtlStyle);
  566.     GlobalUnlock(hRec);
  567.       end;
  568.     wm_Command:
  569.       case wParam of
  570.     idCancel:
  571.       EndDialog(HWindow, 0);
  572.     idOk:
  573.       begin
  574.         hRec := GetProp(HWindow, Prop);
  575.         Rec := GlobalLock(hRec);
  576.         Style := GlobalLock(Rec^.CtlStyle);
  577.         with Rec^, Style^ do
  578.         begin
  579.           { Get caption }
  580.           GetDlgItemText(HWindow, idCaption, szTitle, SizeOf(szTitle));
  581.  
  582.           { Get control id }
  583.           GetDlgItemText(HWindow, idControlId, S, SizeOf(S));
  584.           wId := StrToId(S);
  585.  
  586.           { Get button type }
  587.           if IsDlgButtonChecked(HWindow, idDefaultButton) <> 0 then
  588.         dwStyle := bs_DefPushButton
  589.           else
  590.                 dwStyle := bs_PushButton;
  591.  
  592.           { Get tab stop }
  593.           if IsDlgButtonChecked(HWindow, idTabStop) <> 0 then
  594.         dwStyle := dwStyle or ws_TabStop;
  595.  
  596.           { Get disabled }
  597.           if IsDlgButtonChecked(HWindow, idDisabled) <> 0 then
  598.         dwStyle := dwStyle or ws_Disabled;
  599.  
  600.           { Get group }
  601.           if IsDlgButtonChecked(HWindow, idGroup) <> 0 then
  602.         dwStyle := dwStyle or ws_Group;
  603.         end;
  604.         GlobalUnlock(Rec^.CtlStyle);
  605.         GlobalUnlock(hRec);
  606.         EndDialog(HWindow, 1);
  607.       end;
  608.       else
  609.     BitBtnStyleDlg := 0;
  610.       end;
  611.     wm_Destroy:
  612.       RemoveProp(HWindow, Prop);
  613.   else
  614.     BitBtnStyleDlg := 0;
  615.   end;
  616. end;
  617.  
  618. { BitBtnStyle --------------------------------------------------
  619.     The function will bring up a dialog box to modify the style
  620.     of the button.  Called when the button is double-clicked in
  621.     the dialog editor.
  622.   -------------------------------------------------------------- }
  623. function BitBtnStyle(hWindow: HWnd; CtlStyle: THandle;
  624.   StrToId: TStrToId; IdToStr: TIdToStr): Bool; export;
  625. var
  626.   hRec: THandle;
  627.   Rec: PParamRec;
  628.   hFocus: HWnd;
  629. begin
  630.   BitBtnStyle := False;
  631.   hRec := GlobalAlloc(gmem_Share, SizeOf(TParamRec));
  632.   if hRec <> 0 then
  633.   begin
  634.     Rec := GlobalLock(hRec);
  635.     Rec^.IdToStr := IdToStr;
  636.     Rec^.StrToId := StrToId;
  637.     Rec^.CtlStyle := CtlStyle;
  638.     GlobalUnlock(hRec);
  639.  
  640.     hFocus := GetFocus;
  641.     BitBtnStyle := Bool(DialogBoxParam(HInstance,
  642.       MakeIntResource(idButtonStyle), HWindow, @BitBtnStyleDlg,
  643.       hRec));
  644.     if hFocus <> 0 then SetFocus(hFocus);
  645.     GlobalFree(hRec);
  646.   end;
  647. end;
  648.  
  649. { BitBtnFlags --------------------------------------------------
  650.     Called to decompose the style double word into the .RC
  651.     script expression that it represents.  This only needs to
  652.     decompose the style bits added to the style double word,
  653.     it need not decompose the, for example, the ws_XXX bits.
  654.     The expression returned must be a valid .RC expression
  655.     (i.e. C syntax, case sensitive).
  656.   -------------------------------------------------------------- }
  657. function BitBtnFlags(Style: LongInt; Buff: PChar;
  658.   BuffLength: Word): Word; export;
  659. begin
  660.   if Style and $F = bs_DefPushButton then
  661.     StrLCopy(Buff, 'BS_DEFPUSHBUTTON', BuffLength)
  662.   else StrLCopy(Buff, 'BS_PUSHBUTTON', BuffLength);
  663.   BitBtnFlags := StrLen(Buff);
  664. end;
  665.  
  666. { ListClasses --------------------------------------------------
  667.     Called by Resource Workshop retrieve the information
  668.     necessary to edit the custom controls contain in this DLL.
  669.     This is an alternative to the Microsoft xxxStyle convention.
  670.   -------------------------------------------------------------- }
  671. function ListClasses(szAppName: PChar; wVersion: Word;
  672.   fnLoad: TLoad; fnEdit: TEdit): THandle; export;
  673. var
  674.   hClasses: THandle;
  675.   Classes: PCtlClassList;
  676. begin
  677.   LoadResRW := fnLoad;
  678.   hClasses := GlobalAlloc(gmem_Share or gmem_ZeroInit,
  679.     SizeOf(Integer) + SizeOf(TRWCtlClass));
  680.   if hClasses <> 0 then
  681.   begin
  682.     Classes := GlobalLock(hClasses);
  683.     with Classes^ do
  684.     begin
  685.       nClasses := 1;
  686.       with Classes[0] do
  687.       begin
  688.     fnInfo  := BitBtnInfo;
  689.     fnStyle := BitBtnStyle;
  690.     fnFlags := BitBtnFlags;
  691.       end;
  692.     end;
  693.     GlobalUnlock(hClasses);
  694.   end;
  695.   ListClasses := hClasses;
  696. end;
  697.  
  698. exports
  699.   ListClasses,
  700.   BitButtonWinFn;
  701.  
  702. var
  703.   Class: TWndClass;
  704.  
  705. begin
  706.   with Class do
  707.   begin
  708.     lpszClassName := 'BitButton';
  709.     hCursor       := LoadCursor(0, idc_Arrow);
  710.     lpszMenuName  := nil;
  711.     style         := cs_HRedraw or cs_VRedraw or cs_DblClks or cs_GlobalClass;
  712.     lpfnWndProc   := TFarProc(@BitButtonWinFn);
  713.     hInstance     := System.hInstance;
  714.     hIcon         := 0;
  715.     cbWndExtra    := ofSize;
  716.     cbClsExtra    := 0;
  717.     hbrBackground := 0;
  718.   end;
  719.   RegisterClass(Class);
  720. end.
  721.